/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package fr.ove.openmath.jome.ctrl.mml;

/**
 *
 * @author Mr.Sam
 */
import java.util.*;
import fr.ove.openmath.jome.ctrl.linear.events.*;
import fr.ove.openmath.jome.ctrl.amto.*;
import fr.ove.openmath.jome.ctrl.mml.*;

/**
* A handler for the MathML objects parser.
*
* @author © 2000 DIRAT Laurent
* @version 1.0 25/05/2000
*/
public class MathMLParserHandler {
    private MathMLParserResourcesManager resourcesManager;
    
    private AbstractMathTreeObject amto;
    private MathExpression mathExp;
    
    /**
    * A stack for symbol management.
    */
    private Stack stackSymbol = new Stack(); // Le sommet de cette pile représente le symbol
    
    /**
    * The constructor.<BR>
    * formula must be the root of an empty one.
    */
    public MathMLParserHandler() {
        resourcesManager = new MathMLParserResourcesManager("fr.ove.openmath.jome.ctrl.mml.MathMLParserResources");
        mathExp = new MathExpression();
    }    
    
    /**
    * Sets the event source.<BR>
    * Even if it is the instance which fires the events during the parsing, the instance (as a handler), just...
    * handles the parser. Basically, in a common sense, it is the parser which fires the events. We try to respect
    * the common sense by setting the right event source : the parser.
    * @param eventSource the event source
    */
    public void setEventSource(LinearParserEventSource eventSource) {
        mathExp.setEventSource(eventSource);
    }
    
    /**
    * Receives notification of the beginning of a object element.
    */
    public void startObject() {
        System.out.println("Starting object");
        mathExp.removeAll();
        amto = mathExp;
        
        stackSymbol.push(new Tag("mathml"));
    }

    /**
    * Receives notification of the end of an object element.
    */
    public void endObject() {
        System.out.println("ending object");
        mathExp.flush();
        
        Tag tag = (Tag) stackSymbol.pop();
        if (!tag.getName().equals("mathml"))
            System.out.println("Dommage :o(");
    }

    /**
    * Receives notification of the beginning of a application element.
    */
    public void startApplication() {
        System.out.println("Starting application");
        stackSymbol.push(new Tag("apply"));
    }

    /**
    * Receives notification of the end of an application element.
    */
    public void endApplication() {
        System.out.println("ending application");
        Tag tag  = (Tag) stackSymbol.peek();        
        if (!tag.getName().equals("apply"))
            System.out.println("Dommage :o(");
         else
            amto = amto.getFather();
    }

    /**
    * Receives notification of the beginning of a lambda element.
    */
    public void startLambda() {
        System.out.println("Starting lambda");
        stackSymbol.push("lambda");
    }

    /**
    * Receives notification of the beginning of a bvar element.
    */
    public void startBVars() {
        System.out.println("Starting bound variables");
        stackSymbol.push("bvar");
    }

    /**
    * Receives notification of the end of a bvar element.
    */
    public void endBVars() {
        System.out.println("Ending bound variables");
        Tag tag  = (Tag) stackSymbol.peek();        
        if (!tag.equals("bvar"))
            System.out.println("Fuck you.");
    }

    /**
    * Receives notification of the end of a lambda element.
     */
    public void endLambda() {
        System.out.println("Ending lambda");
        Tag tag  = (Tag) stackSymbol.peek();        
        if (!tag.equals("lambda"))
            System.out.println("Fuck you.");
    }

    /**
    * Receives notification of the beginning of an element.
    */
    public void startElement(Tag tag) {
        System.out.println("Starting elements : " + tag.toString());
        if (!tag.isEmpty())
            stackSymbol.push(tag);
            
        String name = tag.getName();
        
        if (name.equals("cn")) {
            amto = amto.add("integer", null);
        }
        else if (name.equals("ci")) {
            amto = amto.add("variable", null);
        }
        else {
            String identifier = resourcesManager.getIdentifier(name);
            String val = resourcesManager.getValue(name);
            if (val.equals("null"))
                val = null;
                
            amto = amto.add(identifier, val);
        }
    }

    /**
    * Receives notification of the end of an element.
    */
    public void endElement(Tag tag) {
        System.out.println("Ending elements : " + tag.toString());
        Tag topSymbol = (Tag) stackSymbol.pop();        
        if (!tag.isEndTag(topSymbol))
            System.out.println("Fuck you.");
        else
            amto = amto.getFather();
    }
    
    /**
    * Receives notification of the read of an element value.
    */
    public void readValue(String value) {
        System.out.println("read value : " + value);
        amto.setParameter(value);
    }
}
